﻿using System;
using System.IO;

namespace octalforty.Componento.Core.ApplicationServices.Impl
{
    public class Metadirectory
    {
        private const string Co = ".co";
        private const string Lib = "lib";

        private readonly string basePath;
        private readonly string path;

        /// <summary>
        /// Gets a path to the directory where <c>.co</c> is located.
        /// </summary>
        public string BasePath
        {
            get { return basePath; }
        }

        /// <summary>
        /// Gets a path to the <c>.co</c> metadirectory.
        /// </summary>
        public string Path
        {
            get { return path; }
        }

        public Metadirectory(string basePath)
        {
            this.basePath = basePath;
            path = System.IO.Path.Combine(basePath, Co);
        }

        /// <summary>
        /// Initializes directory and file structure at <see cref="basePath"/> and <see cref="path"/>.
        /// </summary>
        public void Initialize()
        {
            if(Directory.Exists(path)) return;

            if(!File.Exists(System.IO.Path.Combine(basePath, "dependencies.co")))
                File.WriteAllText(System.IO.Path.Combine(basePath, "dependencies.co"), @"# Hi! Welcome to Componento! This is where you specify 
# all the packages your application needs. It's also where ""co.exe"" will add packages
# you install via command line.
#
# For example,
# require ""nunit""
# require ""autofac"" [2.2, 2.4)
# require ""moq"" 1.2.3.4
# require ""ninject"" < 2.0");

            Directory.CreateDirectory(path);
            new DirectoryInfo(path).Attributes |= FileAttributes.Hidden;

            var coconfig = System.IO.Path.Combine(path, "coconfig");
            var coversion = System.IO.Path.Combine(path, "coversion");

            if(!File.Exists(coconfig))
                File.WriteAllText(coconfig, @"[repositories]
default = co://packages.componento.net/
nuget = nuget://packages.nuget.org/v1/FeedService.svc/");

            if(!File.Exists(coversion))
                File.WriteAllText(coversion, "0.1");
        }

        public void Upgrade()
        {
        }

        public void AddRepository(string alias, string uri)
        {
            var coconfig = new CoConfig(System.IO.Path.Combine(Path, "coconfig"));
            coconfig.WriteValue("repositories", alias, uri);
        }

        /// <summary>
        /// Probes for a sibling <c>lib</c> directory starting from <paramref name="basePath"/> and working
        /// up towards root. Returns full path to the <c>lib</c> directory or <c>null</c> if nothing found.
        /// </summary>
        /// <param name="basePath"></param>
        /// <returns></returns>
        public static string Probe(string basePath)
        {
            if(Directory.GetParent(basePath) == null) return null;

            var lib = System.IO.Path.Combine(basePath, Lib);
            return Directory.Exists(lib) ? 
                lib : 
                Probe(Directory.GetParent(basePath).FullName);
        }

        public Uri GetRepositoryUri(string alias)
        {
            var coconfig = new CoConfig(System.IO.Path.Combine(Path, "coconfig"));
            var uri = coconfig.ReadString("repositories", alias);
            return string.IsNullOrEmpty(uri) ?
                null :
                new Uri(uri);
        }
    }
}
